#include "BlockQueue.hpp"
#include "Task.hpp"

#include <ctime>
#include <unistd.h>
#include <sys/types.h>

// C：计算
// S: 存储
template <class C, class S>
class BlockQueues
{
public:
    BlockQueue<C> *_cbq;
    BlockQueue<S> *_sbq;
};

void *productor(void *args)
{
    BlockQueue<CalTask> *bq = static_cast<BlockQueues<CalTask, SaveTask> *>(args)->_cbq;

    while (true)
    {
        int x = rand() % 10 + 1;
        int y = rand() % 5;
        char op = oper[rand() % 5];

        CalTask t(x, y, op, calculate);
        bq->push(t);

        std::cout << "productor thread 生产计算任务: " << t.toTaskString() << std::endl;

        sleep(1);
    }

    return nullptr;
}

void *consumer(void *args)
{
    BlockQueue<CalTask> *bq = static_cast<BlockQueues<CalTask, SaveTask> *>(args)->_cbq;
    BlockQueue<SaveTask> *save_bq = static_cast<BlockQueues<CalTask, SaveTask> *>(args)->_sbq;

    while (true)
    {
        CalTask t;
        bq->pop(&t);
        std::string result = t();

        std::cout << "cal thread,完成计算任务: " << result << " ... done" << std::endl;

        SaveTask st(result, Save);
        save_bq->push(st);
        cout << "cal thread,推送存储任务完成..." << std::endl;

        sleep(1);
    }
    return nullptr;
}

void *saver(void *args)
{
    BlockQueue<SaveTask> *save_bq = static_cast<BlockQueues<CalTask, SaveTask> *>(args)->_sbq;

    while (true)
    {
        SaveTask st;
        save_bq->pop(&st);
        st();
        std::cout << "save thread,保存任务完成..." << std::endl;
        // sleep(1);
    }

    return nullptr;
}

int main()
{
    BlockQueues<CalTask, SaveTask> bqs;
    bqs._cbq = new BlockQueue<CalTask>();
    bqs._sbq = new BlockQueue<SaveTask>();

    pthread_t p, c, s;
    pthread_create(&p, nullptr, productor, &bqs);
    pthread_create(&c, nullptr, consumer, &bqs);
    pthread_create(&s, nullptr, saver, &bqs);

    pthread_join(p, nullptr);
    pthread_join(c, nullptr);
    pthread_join(s, nullptr);

    delete bqs._cbq;
    delete bqs._sbq;

    return 0;
}

// void *productor(void *args)
// {
//     BlockQueue<CalTask> *bq = static_cast<BlockQueue<CalTask> *>(args);

//     while (true)
//     {
//         int x = rand() % 10 + 1;
//         int y = rand() % 5;
//         char op = oper[rand() % 5];

//         CalTask t(x, y, op, calculate);
//         bq->push(t);

//         std::cout << "productor thread 生产计算任务: " << t.toTaskString() << std::endl;
//         // sleep(1);
//     }

//     return nullptr;
// }

// void *consumer(void *args)
// {
//     BlockQueue<CalTask> *bq = static_cast<BlockQueue<CalTask> *>(args);

//     while (true)
//     {
//         CalTask t;
//         bq->pop(&t);
//         std::string result = t();

//         std::cout << "cal thread,完成计算任务: " << result << " ... done" << std::endl;
//         sleep(1);
//     }
//     return nullptr;
// }

// int main()
// {
//     srand((unsigned int)time(nullptr) ^ getpid() ^ 0x1234);
//     BlockQueue<CalTask> *bq = new BlockQueue<CalTask>();
//     pthread_t p, c;
//     pthread_create(&p, nullptr, productor, bq);
//     pthread_create(&c, nullptr, consumer, bq);

//     pthread_join(p, nullptr);
//     pthread_join(c, nullptr);

//     delete bq;

//     return 0;
// }
